package com.marco.ipdata.domain;

import com.marco.commons.BeanMapper;
import org.apache.commons.lang3.StringUtils;
import tk.mybatis.mapper.entity.IDynamicTableName;

import javax.persistence.Transient;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.util.Objects;

/**
 * IPBase.java
 * Create on 2017/3/22
 * Copyright(c) JD Inc 2017. All Rights Reserved.
 * <pre>
 * 功能说明：地址的所有共用字段
 * mapper3.3.0以后支持动态表名，关键在于实现IDynamicTableName
 * </pre>
 */
public class IPBase implements Serializable, IDynamicTableName {
    private static final long serialVersionUID = -8816605146893885824L;

    private String ip;
    private String nationId;
    private String provinceId;
    private String cityId;
    private String districtId;
    private String nation;
    private String province;
    private String city;
    private String district;
    private String originAd;
    private String source;
    private String isp;
    private Timestamp updateDateTime;
    //实现动态表名
    @Transient
    private String tableName;

    public IPBase() {
    }

    public IPBase(Builder builder) {
        this.nationId = builder.nationId;
        this.nation = builder.nation;
        this.province = builder.province;
        this.provinceId = builder.provinceId;
        this.city = builder.city;
        this.cityId = builder.cityId;
        this.district = builder.district;
        this.districtId = builder.districtId;
        this.originAd = builder.originAd;
    }

    @Override
    public String getDynamicTableName() {
        return tableName;
    }

    @Override
    public String toString() {
        return String.format("%s|%s|%s|%s|%s|%s|%s|%s|%s", nationId, provinceId, cityId, districtId, nation, province, city,
                district, isp);
    }

    public String output() throws IllegalAccessException {
        //在输出时，同时对结果进行校验
        String ipMin = ip;
        String ipMax = ipMin.substring(0, ipMin.length() - 1) + "255";
        //校验各个参数不为空
        Field[] fields = this.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            if (!field.getName().matches("ip|source|updateDateTime|originAd|tableName")) {
                if (field.get(this) == null) {
                    return "NULL";
                }
            }
        }
        return String.format("%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s", ipMin, ipMax, nationId, provinceId, cityId,
                districtId, nation, province, city, district, isp, source);
    }

    public static IPBase fromStr(String str) {
        if (StringUtils.isBlank(str)) {
            return new IPBase();
        }
        String[] strs = str.split("\\|");
        if (strs.length == 11 || strs.length == 12) {
            Integer startIndex = strs.length - 10;
            IPBase.Builder builder = new IPBase.Builder();
            builder.nationId(strs[startIndex]).provinceId(strs[startIndex + 1])
                    .cityId(strs[startIndex + 2]).districtId(strs[startIndex + 3])
                    .nation(strs[startIndex + 4]).province(strs[startIndex + 5])
                    .city(strs[startIndex + 6]).district(strs[startIndex + 7]);
            IPBase ipBase = new IPBase(builder);
            ipBase.setIp(strs[0]);
            ipBase.setIsp(strs[startIndex + 8]);
            ipBase.setSource(strs[startIndex + 9]);
            return ipBase;
        }
        return new IPBase();
    }

    @Override
    //对于非直辖市，比较到市级，对于直辖市，比较到省级
    public boolean equals(Object o) {
        IPBase tmp = (IPBase) o;
        String provinceId = this.provinceId;
        if (!provinceId.equals(tmp.getProvinceId())) {
            return false;
        }
        if (provinceId.matches("1|2|3|4")) {
            return provinceId.equals(tmp.getProvinceId());
        } else {
            return provinceId.equals(tmp.getProvinceId())
                    && (this.cityId.equals(tmp.getCityId()) || this.cityId.equals("0") || tmp.getCityId().equals("0"));
        }
    }

    //比较两个IP地址是否完全相等[省市区都比较]
    public boolean fullEquals(IPBase ipAddress) {
        boolean flag = false;
        if (Objects.equals(this.provinceId, ipAddress.provinceId)) {
            if (Objects.equals(this.cityId, ipAddress.cityId)) {
                if (Objects.equals(this.districtId, ipAddress.districtId)) {
                    flag = true;
                }
            }
        }
        return flag;
    }


    // 调用equal相等的情况下 A.getAdMerged(B) 将B合并到A中 。最终结果以A为准 ，A的优先级要高于B
    public IPBase getAdMerged(IPBase tmp) {
        IPBase res = new IPBase();
        BeanMapper.copy(this, res);
        //直辖市 合并区
        if (res.getProvinceId().matches("1|2|3|4")) {
            if (cityId.equals("0")) {
                res.setCity(tmp.getCity());
                res.setCityId(tmp.getCityId());
            }
        } else {
            if (cityId.equals("0")) {
                res.setCityId(tmp.getCityId());
                res.setCity(tmp.getCity());
                res.setDistrictId(tmp.getDistrictId());
                res.setDistrict(tmp.getDistrict());
            } else {
                if (districtId.equals("0")) {
                    res.setDistrict(tmp.getDistrict());
                    res.setDistrictId(tmp.getDistrictId());
                }
            }
        }
        if (isp.equals("未知") && !tmp.getIsp().equals("未知")) {
            res.setIsp(tmp.getIsp());
        }
        return res;
    }


    public static class Builder {
        private String nationId;
        private String provinceId;
        private String cityId;
        private String districtId;
        private String nation;
        private String province;
        private String city;
        private String district;
        private String originAd;

        public Builder nationId(String nationId) {
            this.nationId = nationId;
            return this;
        }

        public Builder provinceId(String provinceId) {
            this.provinceId = provinceId;
            return this;
        }

        public Builder cityId(String cityId) {
            this.cityId = cityId;
            return this;
        }

        public Builder districtId(String districtId) {
            this.districtId = districtId;
            return this;
        }

        public Builder nation(String nation) {
            this.nation = nation;
            return this;
        }

        public Builder province(String province) {
            this.province = province;
            return this;
        }

        public Builder city(String city) {
            this.city = city;
            return this;
        }

        public Builder district(String district) {
            this.district = district;
            return this;
        }

        public Builder originAd(String orignAd) {
            this.originAd = orignAd;
            return this;
        }

        public IPBase build() {
            //校验各项不为空
            try {
                for (Field f : this.getClass().getDeclaredFields()) {
                    f.setAccessible(true);
                    if (f.get(this) == null) {
                        throw new Exception("校验抛出异常");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return new IPBase(this);
        }
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public String getNationId() {
        return nationId;
    }

    public void setNationId(String nationId) {
        this.nationId = nationId;
    }

    public String getProvinceId() {
        return provinceId;
    }

    public void setProvinceId(String provinceId) {
        this.provinceId = provinceId;
    }

    public String getCityId() {
        return cityId;
    }

    public void setCityId(String cityId) {
        this.cityId = cityId;
    }

    public String getDistrictId() {
        return districtId;
    }

    public void setDistrictId(String districtId) {
        this.districtId = districtId;
    }

    public String getNation() {
        return nation;
    }

    public void setNation(String nation) {
        this.nation = nation;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getDistrict() {
        return district;
    }

    public void setDistrict(String district) {
        this.district = district;
    }

    public String getOriginAd() {
        return originAd;
    }

    public void setOriginAd(String originAd) {
        this.originAd = originAd;
    }

    public String getSource() {
        return source;
    }

    public void setSource(String source) {
        this.source = source;
    }

    public String getIsp() {
        return isp;
    }

    public void setIsp(String isp) {
        this.isp = isp;
    }

    public Timestamp getUpdateDateTime() {
        return updateDateTime;
    }

    public void setUpdateDateTime(Timestamp updateDateTime) {
        this.updateDateTime = updateDateTime;
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }
}
